import { OnDestroy, OnInit, Component } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { EzFormComponent } from '../ez-form';
import { EzFormControlComponent } from '../ez-form-control';
import { EzFormGroupComponent } from '../ez-form-group';
import { EzFormItemComponent } from '../ez-form-item';
import { EzCheckbox } from './ez-checkbox';
import { EzCheckboxConfiguration, EzCheckboxOptions, EzCheckboxOption } from './ez-checkbox.configuration';
import { takeUntil } from 'rxjs/operators';
declare type EzCheckboxCheckOption = EzCheckboxOption & { checked: boolean };
declare type EzCheckboxCheckOptions = EzCheckboxCheckOption[];

@Component({
  selector: 'ez-checkbox',
  templateUrl: './ez-checkbox.component.html',
  styleUrls: ['./ez-checkbox.component.less'],
  providers: [{ provide: EzFormControlComponent, useExisting: EzCheckboxComponent }],
})
export class EzCheckboxComponent extends EzFormControlComponent<EzCheckboxConfiguration, any>
  implements EzCheckbox, OnInit, OnDestroy {
  loading = false;

  options: EzCheckboxCheckOptions = [];

  private destroy$ = new Subject<any>();

  constructor(
    protected ezForm: EzFormComponent,
    protected ezFormGroup: EzFormGroupComponent,
    protected ezFormItem: EzFormItemComponent
  ) {
    super(ezForm, ezFormGroup, ezFormItem);
  }

  ngOnInit(): void {
    super.ngOnInit();
    this.setOptions(
      this.ezFormControlConfiguration.options instanceof Function
        ? this.ezFormControlConfiguration.options(this, this.ezFormGroup, this.ezForm)
        : this.ezFormControlConfiguration.options
    );
    this.control.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
      this.options.forEach(op => (op.checked = false));
      if (value) {
        if (Array.isArray(value)) {
          this.options.filter(op => value.includes(op.value)).forEach(op => (op.checked = true));
        } else {
          this.options.filter(op => value === op.value).forEach(op => (op.checked = true));
        }
      }
    });
  }

  ngOnDestroy(): void {
    super.ngOnDestroy();
    this.destroy$.next();
    this.destroy$.complete();
  }

  checkConfiguration(configuration: EzCheckboxConfiguration): void {}

  setOptions(options: EzCheckboxOptions | Observable<EzCheckboxOptions> = []) {
    if (options instanceof Observable) {
      options.subscribe(
        ops => {
          this.loading = false;
          this.options = this.setOptionsAndCheckedStatus(ops);
        },
        e => {
          this.loading = false;
          console.error(e);
        }
      );
    } else {
      this.options = this.setOptionsAndCheckedStatus(options);
    }
  }

  private setOptionsAndCheckedStatus(options: EzCheckboxOptions): EzCheckboxCheckOptions {
    this.control.setValue(this.ezFormControlConfiguration.value);
    let values = [];
    if (this.ezFormControlConfiguration.value) {
      if (!Array.isArray(this.ezFormControlConfiguration.value)) {
        values = [this.ezFormControlConfiguration.value];
      } else {
        values = this.ezFormControlConfiguration.value;
      }
    }
    return options.map(op => {
      return {
        ...op,
        checked: values.includes(op.value),
      };
    });
  }

  onNgModelChange(option: EzCheckboxCheckOption, checked: boolean): void {
    let values = [];
    const controlValue = this.control.value;
    if (controlValue) {
      if (!Array.isArray(controlValue)) {
        values.push(controlValue);
      } else {
        values = controlValue;
      }
    }
    const value = option.value;
    if (checked) {
      if (!values.includes(value)) {
        this.control.setValue([...values, value]);
      }
    } else {
      if (values.includes(value)) {
        this.control.setValue(values.filter(v => v !== value));
      }
    }
  }

  optionsDisplayInline(): boolean {
    return (
      this.ezForm.ezFormConfiguration.layout === 'inline' ||
      !(
        this.ezFormControlConfiguration.span === 24 ||
        this.ezForm.ezFormConfiguration.cols === 1 ||
        !this.ezForm.ezFormConfiguration.cols
      )
    );
  }
}
